import BaseScene from "../../../core/BaseScene";
import PopupManager from "../../../core/PopupManager";
import ResManager from "../../../core/ResManager";
import NodeUtil from "../../../utils/NodeUtil";
import { Utils } from "../../../utils/Utils";
import { BattleAnim } from "../../battle/BattleAnim";
import { BattleTest } from "../../data/BattleTest";
import { SkillIconType, WinState } from "../../data/CFCommon";
import ItemSkillIcon from "../items/ItemSkillIcon";
import ItemSkillTip from "../items/ItemSkillTip";
import BattleRoleUi from "./BattleRoleUi";

const { ccclass, property } = cc._decorator;

@ccclass
export default class BattleUi extends BaseScene {

    @property({ type: [cc.Node] })
    owners: Array<cc.Node> = [];

    @property({ type: [cc.Node] })
    enemys: Array<cc.Node> = [];

    @property(cc.Prefab)
    roleUI: cc.Prefab = null;

    @property(cc.Node)
    skillNodes: cc.Node = null;

    @property(cc.Node)
    fightSkillNodes: cc.Node = null;

    @property(cc.Node)
    itemSkillTip: cc.Node = null;

    @property(cc.Prefab)
    itemSkillIcon: cc.Prefab = null;

    @property(cc.Label)
    labFrameNum: cc.Label = null;

    private ownerCtrls: Array<BattleRoleUi> = [];
    private enemyCtrls: Array<BattleRoleUi> = [];
    private frameNum: number = 1;
    private maxFrameNum: number = 30;
    private isEnd: boolean = false;
    private ownerIdx = 0;
    private enemyIdx = 0;
    private maxIdx = 4;
    private winState: WinState = WinState.none;

    private allSkillMap: any = {};
    private fightSkillMap: any = {};
    private maxFightSkillIdx: number = 5;
    private baseAllskills: any = [];
    private curFightSkills: any = [];

    start() {
        BattleTest.ins().init();
        this.initHeros();

        let action = ['skill1', 'skill2', 'run', 'idle', 'die'];
        let btn1 = NodeUtil.getChildByName(this.node, 'btn1');
        btn1.on(cc.Node.EventType.TOUCH_END, () => {
            console.log('btn1 click>>');
            if (BattleTest.ins().isFighting) {
                PopupManager.show('prefabs/PopBox', {
                    title: '提示',
                    content: "战斗中不可以布阵",
                    confirmCallback: () => {
                        console.log('关闭弹窗');
                    }
                });
            } else {
                PopupManager.show('prefabs/popups/PopupFormation', 1);
            }
        }, this);

        this.itemSkillTip.active = false;

        this.addEventListener("onSkillIconClick", this.onSkillIconClick);
        this.addEventListener("ItemSkillIconLongTouch", this.onItemSkillIconLongTouch);
        this.addEventListener("InitBattleUIHeros", this.initHeros);
    }

    onDestroy(): void {
        super.onDestroy();
    }

    initHeros() {
        this.frameNum = 1;
        this.ownerIdx = 0;
        this.enemyIdx = 0;
        this.winState = WinState.none;
        BattleTest.ins().isFighting = false;

        this.allSkillMap = {};
        this.fightSkillMap = {};
        this.baseAllskills = [];
        this.labFrameNum.string = "第{0}回合".format([this.frameNum]);
        this.fightSkillNodes.active = true;

        this.skillNodes.removeAllChildren();
        this.fightSkillNodes.removeAllChildren();
        for (let i = 0; i < this.ownerCtrls.length; i++) {
            this.ownerCtrls[i].node.destroy();
        }
        this.ownerCtrls = [];
        for (let i = 0; i < this.enemyCtrls.length; i++) {
            this.enemyCtrls[i].node.destroy();
        }
        this.enemyCtrls = [];

        this.maxFightSkillIdx = 0;
        for (let i = 0; i < this.owners.length; i++) {
            let idx = i + 1;
            let cardId = BattleTest.ins().ownerMap[idx];
            // console.log("cardId===",cardId)
            if (cardId) {
                let data = BattleTest.ins().getHeroConfigData(cardId);
                let skillData = BattleTest.ins().getSkillData(cardId);
                if (skillData && skillData.skillID) {
                    let node = cc.instantiate(this.itemSkillIcon);
                    this.skillNodes.addChild(node);
                    let itemSkillIconCtrl = node.getComponent(ItemSkillIcon);
                    itemSkillIconCtrl.init(skillData.skillID, idx, SkillIconType.AllSkillIcon);
                    this.allSkillMap[idx] = itemSkillIconCtrl;
                    this.baseAllskills.push(skillData.skillID);

                    let node2 = cc.instantiate(this.itemSkillIcon);
                    this.fightSkillNodes.addChild(node2);
                    let itemSkillIconCtrl2 = node2.getComponent(ItemSkillIcon);
                    itemSkillIconCtrl2.clear();
                    this.fightSkillMap[idx] = itemSkillIconCtrl2;

                    this.maxFightSkillIdx++;
                }
                if (data) {
                    let node = cc.instantiate(this.roleUI);
                    this.owners[i].addChild(node);
                    let ownerCtrl = node.getComponent(BattleRoleUi);
                    ownerCtrl.init(true, { cardId: cardId, hp: data.hp, power: 1, atk: data.atk, spinePath: data.heroFight, skillId: skillData.skillID });
                    this.ownerCtrls[i] = ownerCtrl
                }
            }
        }

        for (let i = 0; i < this.owners.length; i++) {
            let cardId = BattleTest.ins().enemyMap[i + 1]
            if (cardId) {
                let data = BattleTest.ins().getHeroConfigData(cardId);
                if (data) {
                    let node = cc.instantiate(this.roleUI);
                    this.enemys[i].addChild(node);
                    let enemyCtrl = node.getComponent(BattleRoleUi);
                    enemyCtrl.init(false, { cardId: cardId, hp: data.hp, power: 1, atk: data.atk, spinePath: data.heroFight, skillId: -1 });
                    this.enemyCtrls[i] = enemyCtrl
                }
            }
        }
    }



    onItemSkillIconLongTouch(skillId) {
        this.itemSkillTip.active = true;
        let itemSkillTipCtrl = this.itemSkillTip.getComponent(ItemSkillTip);
        itemSkillTipCtrl.init(skillId);
    }

    onSkillIconClick(skillId, idx, type, callback) {
        // console.log("skillid1==", skillId, ",idx1==", idx);
        if (skillId == 0 || BattleTest.ins().isFighting) return;
        if (callback) callback();
        let fightSkillIdx = 1;
        for (let i = 1; i <= this.maxFightSkillIdx; i++) {
            let skillId = this.fightSkillMap[i].getSkillId();
            // console.log("skillId==", skillId)
            if (skillId > 0) {
                fightSkillIdx++;
            } else {
                break;
            }
        }
        if (fightSkillIdx > this.maxFightSkillIdx) {
            return;
        }
        if (type == SkillIconType.AllSkillIcon) {
            this.allSkillMap[idx].node.active = false;
            this.fightSkillMap[fightSkillIdx].init(skillId, idx, SkillIconType.FightSkillIcon);
        } else if (type == SkillIconType.FightSkillIcon) {
            this.allSkillMap[idx].node.active = true;
            // this.fightSkillMap[fightSkillIdx].clear();
        }

        let fightSkillNum = 0;
        for (let i = 1; i <= this.maxFightSkillIdx; i++) {
            if (this.fightSkillMap[i]) {
                let skillId = this.fightSkillMap[i].getSkillId();
                if (skillId > 0) {
                    fightSkillNum++;
                }
            }
        }
        if (fightSkillNum == this.maxFightSkillIdx) {
            //开始战斗
            BattleTest.ins().isFighting = true;
            this.scheduleOnce(() => {
                this.reSetAllSkillMap();
                this.clearFightSkillMap();
                this.run();
            }, 0.5);
        }
    }

    clearFightSkillMap(isShow = false) {
        for (let i = 1; i <= Utils.getObjLength(this.fightSkillMap); i++) {
            this.fightSkillMap[i].node.active = false;
        }
        for (let i = 1; i <= this.maxFightSkillIdx; i++) {
            this.fightSkillMap[i].node.active = true;
            this.fightSkillMap[i].clear();
        }
        this.fightSkillNodes.active = isShow;
    }

    reSetAllSkillMap() {
        this.curFightSkills = [];
        this.maxFightSkillIdx = 0;
        for (let i = 1; i <= Utils.getObjLength(this.fightSkillMap); i++) {
            let skillId = this.fightSkillMap[i].getSkillId();
            // console.log("skillId==", skillId)
            let curOwnerCtrl = this.getOwnerCtrlBySkillId(skillId);
            if (skillId > 0 && curOwnerCtrl.getHp() > 0) {
                this.maxFightSkillIdx++;
                this.allSkillMap[i].node.active = true;
                this.allSkillMap[i].init(skillId, i, SkillIconType.AllSkillIcon);
                this.curFightSkills.push(skillId);
            }
        }
    }

    ready() {
        this.maxFightSkillIdx = 0;
        for (let i = 0; i < this.baseAllskills.length; i++) {
            let skillId = this.baseAllskills[i];
            let curOwnerCtrl = this.getOwnerCtrlBySkillId(skillId);
            if (curOwnerCtrl.getHp() > 0) {
                this.maxFightSkillIdx++;
                this.allSkillMap[i + 1].node.active = true;
                this.allSkillMap[i + 1].init(skillId, i + 1, SkillIconType.AllSkillIcon);
            }
        }
        this.clearFightSkillMap(true);
    }

    showItemSkillTip(skillId, idx) {
        this.itemSkillTip.active = true;
        let itemSkillTipCtrl = this.itemSkillTip.getComponent(ItemSkillTip);
        itemSkillTipCtrl.init(skillId);
        this.scheduleOnce(() => {
            this.itemSkillTip.active = false;
            this.allSkillMap[idx].node.active = false;
        }, 1)
    }

    checkWin(isOwner: boolean) {
        let win = true
        if (isOwner) {
            for (let i = 0; i < this.enemyCtrls.length; i++) {
                if (this.enemyCtrls[i].getHp() > 0) {
                    win = false
                    break;
                }
            }
            if (win) {
                this.winState = WinState.win;
            }
        } else {
            for (let i = 0; i < this.ownerCtrls.length; i++) {
                if (this.ownerCtrls[i].getHp() > 0) {
                    win = false
                    break;
                }
            }
            if (win) {
                this.winState = WinState.lose;
            }
        }
        if (win) {
            let tps = ["", "我方胜利", "敌方胜利"];
            this.scheduleOnce(() => {
                PopupManager.show('prefabs/PopBox', {
                    title: '提示',
                    content: tps[this.winState],
                    confirmCallback: () => {
                        BattleTest.ins().isFighting = false;
                    }
                })
            }, 1);
        }
    }

    getOwnerCtrlBySkillId(skillId) {
        let ownerCtrl = null
        for (const key in this.ownerCtrls) {
            if (Object.prototype.hasOwnProperty.call(this.ownerCtrls, key)) {
                const element = this.ownerCtrls[key];
                if (skillId == element.getData().skillId) {
                    ownerCtrl = element;
                    break;
                }
            }
        }
        return ownerCtrl;
    }

    ownersAtk() {
        let next = () => {
            if (this.winState != WinState.none) return;
            this.ownerIdx++;
            if (this.ownerIdx > this.maxIdx) {
                this.frameNum++;
                this.labFrameNum.string = "第{0}回合".format([this.frameNum]);
                this.run();
            } else {
                this.ownersAtk();
            }
        }
        // let curOwnerCtrl = this.ownerCtrls[this.ownerIdx];
        let skillId = this.curFightSkills[this.ownerIdx];
        let config_skill = ResManager.ins().getRes('config_skill');
        let skillInfo = config_skill[skillId];
        let curOwnerCtrl = this.getOwnerCtrlBySkillId(skillId);

        if (curOwnerCtrl && curOwnerCtrl.getHp() > 0) {
            let liveEnemyCtrls = []
            for (let i = 0; i < this.enemyCtrls.length; i++) {
                if (this.enemyCtrls[i].getHp() > 0) {
                    liveEnemyCtrls.push(this.enemyCtrls[i]);
                }
            }

            let targetNum = skillInfo.targetNum
            if (targetNum == -1 || targetNum > liveEnemyCtrls.length) {
                targetNum = liveEnemyCtrls.length
            }

            curOwnerCtrl.doAction("skill2");
            this.showItemSkillTip(skillId, this.ownerIdx + 1);
            for (let i = 0; i < targetNum; i++) {
                if (liveEnemyCtrls[i]) {
                    this.scheduleOnce(() => {
                        let value = BattleTest.ins().getSkillValue(curOwnerCtrl.getData().cardId);
                        liveEnemyCtrls[i].updateHp(value);

                        let obj = {
                            nodeRoleAtk: curOwnerCtrl.node,
                            nodeRoleDef: liveEnemyCtrls[i].node,
                            skillId: skillId
                        }
                        if (skillInfo.flyAnim) {
                            BattleAnim.ins().doCreatrFlightEffect(obj, false, this.node);
                        }
                        if (skillInfo.dropAnim) {
                            BattleAnim.ins().doCreatrInjectEffect(obj);
                        }
                        if (skillInfo.hitAnim) {
                            BattleAnim.ins().doCreatrHurtEffect(obj);
                        }

                        if (liveEnemyCtrls[i].getHp() <= 0) {
                            liveEnemyCtrls[i].onDead();
                            this.checkWin(true);
                        }
                    }, 1);
                }
            }
            this.scheduleOnce(() => {
                next();
            }, 2);
        } else {
            next();
        }
    }

    enemysAtk() {
        let next = () => {
            if (this.winState != WinState.none) return;
            this.enemyIdx++;
            if (this.enemyIdx > this.maxIdx) {
                this.frameNum++;
                this.labFrameNum.string = "第{0}回合".format([this.frameNum]);
                BattleTest.ins().isFighting = false;
                this.ready();
                // this.run();
            } else {
                this.enemysAtk();
            }
        }
        let curEnemyCtrl = this.enemyCtrls[this.enemyIdx];
        let skillInfo = BattleTest.ins().getSkillData(curEnemyCtrl.getData().cardId)
        if (curEnemyCtrl && curEnemyCtrl.getHp() > 0) {
            let liveOwnerCtrls = []
            for (let i = 0; i < this.ownerCtrls.length; i++) {
                if (this.ownerCtrls[i].getHp() > 0) {
                    liveOwnerCtrls.push(this.ownerCtrls[i]);
                }
            }

            let targetNum = skillInfo.targetNum
            if (targetNum == -1 || targetNum > liveOwnerCtrls.length) {
                targetNum = liveOwnerCtrls.length
            }
            for (let i = 0; i < targetNum; i++) {
                if (liveOwnerCtrls[i]) {
                    curEnemyCtrl.doAction("skill2");
                    this.scheduleOnce(() => {
                        let value = BattleTest.ins().getSkillValue(curEnemyCtrl.getData().cardId);
                        liveOwnerCtrls[i].updateHp(value);

                        let obj = {
                            nodeRoleAtk: curEnemyCtrl.node,
                            nodeRoleDef: liveOwnerCtrls[i].node,
                            skillId: skillInfo.skillID
                        }
                        if (skillInfo.flyAnim) {
                            BattleAnim.ins().doCreatrFlightEffect(obj, false, this.node);
                        }
                        if (skillInfo.dropAnim) {
                            BattleAnim.ins().doCreatrInjectEffect(obj);
                        }
                        if (skillInfo.hitAnim) {
                            BattleAnim.ins().doCreatrHurtEffect(obj);
                        }

                        if (liveOwnerCtrls[i].getHp() <= 0) {
                            liveOwnerCtrls[i].onDead();
                            this.checkWin(false);
                        }
                    }, 1);
                }
            }

            this.scheduleOnce(() => {
                next();
            }, 2);
        } else {
            next();
        }
    }

    run() {
        this.ownerIdx = 0;
        this.enemyIdx = 0;
        if (this.frameNum >= this.maxFrameNum) {
            this.winState = WinState.timeout;
            this.scheduleOnce(() => {
                PopupManager.show('prefabs/PopBox', {
                    title: '提示',
                    content: '游戏回合超过',
                    confirmCallback: () => {
                    }
                });
            }, 1);
            return;
        }
        if (this.frameNum % 2 == 0) {
            this.enemysAtk()
        } else {
            this.ownersAtk()
        }
    }
}
